import socket
import threading

import buff
from utils import logging
from handler import BaseHandler
from buff import Buff
from protocol import Protocol, TEXT_MESSAGE, JSON_MESSAGE, FILE_MESSAGE


class TCPServer(object):

    def __init__(self, host: str, port: int, handler_cls):
        self.server_address = (host, port)
        self.handler_cls: BaseHandler = handler_cls

        # 初始化套接字对象
        self.__socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.__socket.bind(self.server_address)
        self.__socket.listen(5)

        # 是否关闭状态
        self.__is_shutdown: bool = True

        # 客户端列表, 存在字典里 key 是客户端地址, value 是对应的客户端 handler 实例
        self.client_list: dict = {}

        # 客户端json列表, 给前端用的 {'ip:port': {information}}
        # self.client_list_obj: dict = {}

    def run_server(self):
        self.__is_shutdown = False

        threading.Thread(target=self.__run).start()

    def __run(self):

        logging.info("服务器运行在 {}:{}".format(self.server_address[0], self.server_address[1]))

        while not self.__is_shutdown:
            try:
                client, remote_address = self.__socket.accept()
            except Exception as e:
                break

            threading.Thread(target=self.on_connection, args=(client, remote_address)).start()

    def on_connection(self, client: socket.socket, remote_address: tuple):
        handler: BaseHandler = self.handler_cls(client, remote_address, self)
        self.client_list["%s:%d" % (remote_address[0], remote_address[1])] = handler
        self.wait_recv(handler)

    def wait_recv(self, handler: BaseHandler):
        while handler.is_connection:
            try:
                request: Protocol = Protocol.handler(buff=handler.buff)

                if request is None:
                    """
                    数据包结构错误
                    """
                    handler.on_connect_err('ProtocolError', descriotion="数据包结构错误, 已断开链接")

                    break

                if request.body == b'':
                    handler.on_connect_err('ConnectionResetError', descriotion="远程主机主动断开连接")

                    break

            except ConnectionResetError:
                """
                异常处理, ConnectionResetError 远程主机主动断开连接
                该异常是对方主动与我方断开连接,
                """

                handler.on_connect_err('ConnectionResetError', descriotion="远程主机主动断开连接")

                break

            except ConnectionAbortedError:
                """
                异常处理, ConnectionAbortedError 你的主机中软件终止了一个已建立的连接
                该异常是我方主动与对方断开连接,
                """

                handler.on_connect_err('ConnectionAbortedError', descriotion="你的主机中软件终止了一个已建立的连接")

                break

            except Exception:
                """
                异常处理, 奇奇怪怪的异常处理,
                该异常处理其他异常
                """
                handler.on_connect_err('OtherError', descriotion="异常处理, 奇奇怪怪的异常处理")

                return None, True

            handler.on_message(request)

        return False

    def send(self, protocol: Protocol, target=None):
        """
        发送消息

        :param protocol:
        :param target:
        :return:
        """
        # 先判断目标是不是空, 是空为广播
        if target is None:
            for key in list(self.client_list):
                client: BaseHandler = self.client_list[key]

                try:
                    client.send(protocol)
                except Exception:
                    client.on_connect_err('ConnectionSendError', descriotion="发送信息失败, 连接可能已经断开")
                    del self.client_list[key]
                    # del self.client_list_obj[key]

        # 指定目标就发送给指定客户端
        else:
            client = self.client_list[target]

            try:
                client.send(protocol)
            except Exception:
                client.on_connect_err('ConnectionSendError', descriotion="发送信息失败, 连接可能已经断开")
                del self.client_list[target]
                # del self.client_list_obj[target]

    def node_disconnection(self, remote_address):
        host = f"{remote_address[0]}:{remote_address[1]}"
        del self.client_list[host]
        # del self.client_list_obj[host]

    @property
    def is_shutdown(self):
        return self.__is_shutdown

    def close(self):
        # is Shutdown
        self.__is_shutdown = True

        # 关闭套接字连接
        self.__socket.close()

        # 清空列表
        self.client_list.clear()
        # self.client_list_obj.clear()

        logging.info("服务器已关闭 {}:{}".format(self.server_address[0], self.server_address[1]))

    @property
    def is_run(self):
        return not self.__is_shutdown


class SimpleHandler(BaseHandler):

    def before_request_middleware(self, request: Protocol) -> bool:
        if request.header.get("test") and request.header.get("test") == "Test Header":
            return True
        return False

    def text_handler(self, request: Protocol):
        print("type: ", request.type)
        print("version: ", request.version)
        print("header: ", request.header)
        print(request.body.decode("utf-8"))

    def json_handler(self, request: Protocol):
        pass

    def file_handler(self, request: Protocol):
        pass


if __name__ == '__main__':
    server = TCPServer("127.0.0.1", 8848, SimpleHandler)
    server.run_server()

    while server.is_run:
        data = input()

        if data == "exit":
            server.node_disconnection()
            break

        p = Protocol(TEXT_MESSAGE, data)
        p.set_header("test", "Test Header")
        server.send(p)
